/*
 * Copyright 2009-2010 Nanjing RedOrange ltd (http://www.red-orange.cn)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package redora.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

import javax.xml.XMLConstants;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.jetbrains.annotations.NotNull;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;


/**
 * schema validation.
 *
 * @author Nanjng RedOrange (www.red-orange.cn)
 *
 */
public class SchemaValidator {

    private final Validator validator;

    /**
     * Initializer SchemaValidator against given schemaFile.
     */
    public SchemaValidator(@NotNull Class<?> clz, @NotNull String schemaFile)
           throws SAXException {
        File localFile = new File("src" + File.separator + "main"
                + File.separator + "resources" + File.separator
                + "model" + File.separator + "xsd"
                + File.separator + schemaFile);
        Schema schema;
        if (localFile.exists()) {
            try {
                schema = createSchema(new FileInputStream(localFile));
            } catch (FileNotFoundException e) {
                schema = createSchema(clz.getResourceAsStream(
                        "/model/xsd/" + schemaFile));
            }
        } else {
            schema = createSchema(clz.getResourceAsStream(
                    "/model/xsd/" + schemaFile));
        }
        validator = schema.newValidator();
        validator.setFeature(
                        "http://apache.org/xml/features/validation/schema-full-checking",
                        true);
    }

    /**
     * Creates a SchemaValidator against schemaFile.
     */
    public SchemaValidator(@NotNull InputStream schemaFile) throws SAXException {
        Schema schema = createSchema(schemaFile);
        validator = schema.newValidator();
        validator.setFeature(
                        "http://apache.org/xml/features/validation/schema-full-checking",
                        true);
    }

    /**
     * validate xml file according to xsd file.
     */
    public void validate(@NotNull File xml, @NotNull ErrorHandler errorHandler)
            throws SAXException, IOException {
        validator.setErrorHandler(errorHandler);
        validator.validate(new StreamSource(xml));
    }

    /**
     * validate xml inputStream according to xsd file.
     */
    public void validate(@NotNull InputStream xml, @NotNull ErrorHandler errorHandler)
            throws SAXException, IOException {
        validator.setErrorHandler(errorHandler);
        validator.validate(new StreamSource(xml));
    }

    /**
     *
     * verify xml file validation.
     *
     * @return schema
     *
     * @throws SAXException
     */
    private Schema createSchema(@NotNull InputStream schemaStream)
              throws SAXException {
        SchemaFactory schemaFactory = SchemaFactory
                .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        return schemaFactory.newSchema(new StreamSource(schemaStream));
    }
}
